﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MWControlSuite;
using ObservadorPeplau.API;
using ObservadorPeplau.API.Business;

namespace ObservadorPeplau.Usercontrols
{
    public partial class CommentTree : UserControl
    {
        public delegate void CommentTreeEvent(CommentTree tree);
        public CommentTreeEvent TreeMouseLeave { get; set; }
        public CommentTreeEvent TreeNodesChanged { get; set; }

        public delegate void CommentTreeEventNode(CommentTree tree, TreeNode node, Comment comment);
        public CommentTreeEventNode NodeMouseHover { get; set; }

        public Discussion Discussion { get; set; }
        public List<Comment> Comments
        {
            get { return (Discussion != null) ? Discussion.Comments : new List<Comment>(); }
        }

        public CommentTree()
        {
            InitializeComponent();
        }

        public void Bind()
        {
            TreeView.Nodes.Clear();
            foreach (var comment in Comments)
                TreeView.Nodes.Add(NewTreeViewNodeFromComment(comment));

            TreeView.ExpandAll();

            SetButtomStates();
        }

        public Comment GetSelectedComment()
        {
            return TreeView.SelectedNode == null ? null : GetCommentById(TreeView.SelectedNode.Name);
        }

        public void ChangeReadRecursively(bool isRead, Comment comment = null)
        {
            // Mark item as read
            if (comment != null)
                comment.IsRead = isRead;

            // Mark Children as read            
            var lstComments = (comment == null) ? Comments : comment.Children;
            foreach (var childComment in lstComments)
                ChangeReadRecursively(isRead, childComment);
        }

        public List<Comment> GetReadComments(Comment comment = null)
        {
            var lstComments = (comment == null) ? Comments : comment.Children;
            return lstComments.Where(p => p.IsRead).ToList();
        }

        public List<Comment> GetUnReadComments(Comment comment = null)
        {
            var lstComments = (comment == null) ? Comments : comment.Children;
            return lstComments.Where(p => !p.IsRead).ToList();
        }

        private void SetButtomStates()
        {
            labMarkAllAs.Enabled = (TreeView.Nodes.Count > 0);
            btnMarkAllRead.Enabled = GetUnReadComments().Count > 0;
            btnMarkAllUnread.Enabled = GetReadComments().Count > 0;
        }

        private Comment GetCommentById(string nodeId, Comment parent = null)
        {
            var lstNodes = Comments;
            if (parent != null)
                lstNodes = parent.Children;

            // Found in the first level
            if (lstNodes.Count(p => p.Id.ToString() == nodeId) > 0)
                return lstNodes.First(p => p.Id.ToString() == nodeId);
            
            // Deeper levels
            foreach (Comment parentNode in lstNodes)
            {
                if (parentNode.Children.Count == 0)
                    continue;

                var childNode = GetCommentById(nodeId, parentNode);
                if (childNode != null)
                    return childNode;
            }

            // Not Found
            return null;
        }

        private TreeNode NewTreeViewNodeFromComment(Comment comment)
        {
            // Parent
            var thisNode = new TreeNode
                               {
                                   Text = comment.TextWithoutHtml,
                                   ToolTipText = comment.Author.Name + ", " + comment.DateTime.ToString(),                                   
                                   Name = comment.Id.ToString(),
                                   NodeFont = new Font(Font.Name, Font.Size, (comment.IsRead) ? FontStyle.Regular : FontStyle.Bold)                                   
                               };
            // Children
            foreach (var childComment in comment.Children)
                thisNode.Nodes.Add(NewTreeViewNodeFromComment(childComment));

            return thisNode;
        }

        private void rightClickMenu_Opening(object sender, CancelEventArgs e)
        {
            var selectedComment = GetSelectedComment();
            if (selectedComment == null)
            {
                e.Cancel = true;
                return;
            }

            e.Cancel = false;
            rightClickMenu.Items.Clear();
            rightClickMenu.Items.Add(selectedComment.IsRead ? Constants.MarkAsUnread : Constants.MarkAsRead);
        }

        private void rightClickMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            var selectedComment = GetSelectedComment();
            selectedComment.IsRead = (e.ClickedItem.Text == Constants.MarkAsRead);

            Bind();

            if (TreeNodesChanged != null)
                TreeNodesChanged(this);
        }

        private void btnMarkAllUnread_Click(object sender, EventArgs e)
        {
            ChangeReadRecursively(false);

            Bind();

            if (TreeNodesChanged != null)
                TreeNodesChanged(this);
        }

        private void btnMarkAllRead_Click(object sender, EventArgs e)
        {
            ChangeReadRecursively(true);
            Bind();

            if (TreeNodesChanged != null)
                TreeNodesChanged(this);
        }

        private void TreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
                TreeView.SelectedNode = e.Node;
        }

        private void TreeView_NodeMouseHover(object sender, TreeNodeMouseHoverEventArgs e)
        {
            if (NodeMouseHover!=null)
                NodeMouseHover(this, e.Node, GetCommentById(e.Node.Name));
        }

        private void TreeView_MouseLeave(object sender, EventArgs e)
        {
            if (TreeMouseLeave != null)
                TreeMouseLeave(this);
        }
    }
}
